package com.wodan.zhongjinjicang.common.orm.command.write;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.Callable;

import com.wodan.zhongjinjicang.common.orm.command.base.AbstractSqlCommandExecutor;
import com.wodan.zhongjinjicang.common.orm.metadata.MethodMetaData;
import com.wodan.zhongjinjicang.common.orm.metadata.TableFieldMetaData;
import com.wodan.zhongjinjicang.common.orm.metadata.TableMetaData;
import com.wodan.zhongjinjicang.common.orm.utils.SqlGenernateUtils;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.ibatis.mapping.SqlCommandType;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;


/**
 * 通用的sql更新执行器
 * 
 * @ClassName: SqlInsertExecutor
 * @author Administrator
 * @date 2015-11-5 下午4:43:12
 * @history
 * 
 */
public class SqlUpdateCommonExecutor extends AbstractSqlCommandExecutor {
	@Override
	protected Object doExecute(final TableMetaData tableMetaData, MethodMetaData methodMetaData,
							   Object[] args) {
		Assert.notEmpty(args);
		Assert.isTrue(args.length >= 2);

		// 获取set列的映射
		Map<String, Object> setColumnNameValueMap = resolveSetColumnNameValueMap(tableMetaData, methodMetaData, args);
		if (CollectionUtils.isEmpty(setColumnNameValueMap)) {
			throw new IllegalArgumentException("方法[" + methodMetaData.getMethod() + "]执行更新时@UpdateSetField对应字段为空，参数为["
					+ JSON.toJSONString(args) + "]");
		}

		// 获取查询条件映射
		Map<String, Object> conditionColumnNameMap = resolveConditionColumnNameValueMap(tableMetaData, methodMetaData,
				args);
		if (CollectionUtils.isEmpty(conditionColumnNameMap)) {
			throw new IllegalArgumentException("方法[" + methodMetaData.getMethod() + "]执行更新时@UpdateSetField字段为空，参数为["
					+ JSON.toJSONString(args) + "]");
		}

		// 创建sql语句的必须元素
		final String tableName = tableMetaData.getTableName();
		final String[] setColumns = setColumnNameValueMap.keySet().toArray(new String[setColumnNameValueMap.size()]);
		final String[] conditionColumns = conditionColumnNameMap.keySet().toArray(
				new String[conditionColumnNameMap.size()]);
		@SuppressWarnings("unchecked")
		final Object[] setAndCoditionValues = ArrayUtils.toArray(Object.class, Lists.newArrayList(setColumnNameValueMap.values(), conditionColumnNameMap.values()));

		// 生成sql语句
		final String sql = super.createCachedSqlScript(new Callable<String>() {
			@Override
			public String call() throws Exception {
				return SqlGenernateUtils.createUpdateSql(tableName, setColumns, conditionColumns);
			}
		}, tableName, setColumns, conditionColumns);

		// 执行sql语句
		return jdbcTemplate.update(sql, setAndCoditionValues);
	}

	private Map<String, Object> resolveSetColumnNameValueMap(TableMetaData tableMetaData,
															 MethodMetaData methodMetaData, Object[] args) {
		Map<String, Object> setFieldNameValueMap = methodMetaData.resolveSetFieldNameValueMap(args);

		// 从表中获取id字段
		TableFieldMetaData idField = tableMetaData.getIdField();
		// 移除set字段中的id字段
		setFieldNameValueMap.remove(idField.getFieldName());

		return super.convertFieldMapToColumnMap(tableMetaData, setFieldNameValueMap);
	}

	@Override
	public Method getProxyMethod() {
		throw new UnsupportedOperationException("当前实现类不支持此方法");
	}

	@Override
	protected boolean isEntityMustHaveIdField() {
		return true;
	}

	@Override
	public SqlCommandType getSqlCommandType() {
		return SqlCommandType.UPDATE;
	}
}
